home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / macabuse / imlib / palette.c < prev    next >
C/C++ Source or Header  |  1997-05-20  |  11KB  |  518 lines

  1. #include "palette.hpp"
  2. #include "image.hpp"
  3. #include "macs.hpp"
  4. #include "dos.h"
  5. #include "video.hpp"
  6. #include "filter.hpp"
  7. #include "jmalloc.hpp"
  8. #include "dprint.hpp"
  9. #include <math.h>
  10.  
  11. palette *lastl=NULL;
  12.  
  13. palette::palette(bFILE *fp)
  14. {
  15.   ncolors=fp->read_short();
  16.   pal=(color *)jmalloc(sizeof(color)*ncolors,"palette");
  17.   usd=(unsigned char *)jmalloc(ncolors/8+1,"palette used array");
  18.   set_all_unused();
  19.   fp->read(pal,sizeof(color)*ncolors);
  20.   bg=0;
  21. }
  22.  
  23. palette::palette(spec_entry *e, bFILE *fp)
  24. {
  25.   fp->seek(e->offset,0);
  26.   ncolors=fp->read_short();
  27.   pal=(color *)jmalloc(sizeof(color)*ncolors,"palette");
  28.   usd=(unsigned char *)jmalloc(ncolors/8+1,"palette used array");
  29.   set_all_unused();
  30.   fp->read(pal,sizeof(color)*ncolors);
  31.   bg=0;
  32. }
  33.  
  34. int palette::size()
  35. {
  36.   return ncolors*sizeof(color)+2;
  37. }
  38.  
  39. int palette::write(bFILE *fp)
  40. {
  41.   fp->write_short(ncolors);
  42.   return fp->write(pal,sizeof(color)*ncolors)==ncolors;
  43. }
  44.  
  45. int palette::find_closest(unsigned char r, unsigned char g, unsigned char b)
  46. {
  47.    unsigned char *cl=(unsigned char *)addr();
  48.    int c=0,d=0x100000,i,nd;
  49.    for (i=0;i<256;i++)
  50.    {
  51.      nd=((int)r-(int)(*cl))*((int)r-(int)(*cl)); cl++;
  52.      nd+=((int)g-(int)(*cl))*((int)g-(int)(*cl)); cl++;
  53.      nd+=((int)b-(int)(*cl))*((int)b-(int)(*cl)); cl++;
  54.      if (nd<d)
  55.      { c=i; d=nd; }
  56.    }
  57.    return c;
  58. }
  59.  
  60. int palette::find_color(unsigned char r, unsigned char g, unsigned char b)
  61. {
  62.   int i,ub,mask,find;
  63.   for (i=0,ub=0,mask=128,find=-1;i<ncolors && find<0;i++)
  64.   {
  65.     if (usd[ub]&mask)
  66.       if (r==pal[i].red && b==pal[i].blue && g==pal[i].green)
  67.     find=i;
  68.     mask>>=1;
  69.     if (mask==0)
  70.     { mask=128; ub++; }
  71.   }
  72.   return find;
  73. }
  74.  
  75. long palette::getquad(int x)
  76. { char entry[4];
  77.   entry[3]=0;
  78.   entry[2]=pal[x].red;
  79.   entry[1]=pal[x].green;
  80.   entry[0]=pal[x].blue;
  81.   return *((long *)entry);
  82. }
  83.  
  84.  
  85. void palette::black_white()
  86. {
  87.   int i;
  88.   unsigned char r,g,b,gr;
  89.  
  90.   for (i=0;i<256;i++)
  91.   {
  92.     get(i,r,g,b);
  93.     gr=(unsigned char)((double) r*0.30+(double) g*0.59+(double)b*0.11);
  94.     set(i,gr,gr,gr);
  95.   }
  96. }
  97.  
  98. void palette::make_black_white()
  99. {
  100.   int i,c;
  101.   set(0,0,0,0);
  102.   for (i=1;i<ncolors;i++)
  103.   { c=(int)((double)i/(double)ncolors*(double)255);
  104.     set(i,c,c,c);
  105.   }
  106. }
  107.  
  108. void palette::set_rgbs()
  109. {
  110.   int i,v;
  111.   CHECK(ncolors==256);
  112.   for (i=0;i<64;i++)
  113.   {
  114.     if (i==0) v=0;
  115.     else
  116.     {
  117.       v=(int) ((double)i+(double)(sqrt(63-i)));
  118.       v<<=2;
  119.     }
  120.  
  121.     set(i,         i,     0,     0);            // reds 0-63
  122.     set(i+64,      0,     i,     0);
  123.     set(i+128,     0,     0,     i);       // blues 128-191
  124.     set(i+128+64,  v,     v,     v);        // whites .. rest
  125.   }
  126.   set_all_used();
  127. }
  128.  
  129. void palette::set_all_used()
  130. {
  131.   int i;
  132.   for (i=0;i<ncolors;i++) set_used(i);
  133. }
  134.  
  135. void palette::set_all_unused()
  136. {
  137.   int i;
  138.   for (i=0;i<ncolors;i++) set_unused(i);
  139. }
  140.  
  141.  
  142. palette *palette::copy()
  143. {
  144.   palette *p;
  145.   int i;
  146.   p=new palette(ncolors);
  147.   for (i=0;i<ncolors;i++)
  148.   {
  149.     if (used(i))
  150.       p->set_used(i);
  151.     else p->set_unused(i);
  152.     p->set(i,red(i),green(i),blue(i));
  153.   }
  154.   return p;
  155. }
  156.  
  157. void palette::set_used(int color_num)
  158. {
  159.   int x,b;
  160.   CHECK(color_num>=0 && color_num<ncolors);
  161.   x=color_num/8;
  162.   b=color_num%8;
  163.   usd[x]|=(128>>b);
  164. }
  165.  
  166. void palette::set_unused(int color_num)
  167. {
  168.   int x,b;
  169.   CHECK(color_num>=0 && color_num<ncolors);
  170.   x=color_num/8;
  171.   b=color_num%8;
  172.   usd[x]&=(0xff^(128>>b));
  173. }
  174.  
  175. int palette::used(int color_num)
  176. {
  177.   int x,b;
  178.   CHECK(color_num>=0 && color_num<ncolors);
  179.   x=color_num/8;
  180.   b=color_num%8;
  181.   return (usd[x]&(128>>b));
  182. }
  183.  
  184. int palette::add_color(unsigned int r, int unsigned g, int unsigned b, int closest_only)
  185. {
  186.   int i,f,u,c;
  187.   if (!closest_only)
  188.   {
  189.     for (i=ncolors-1,f=-1,u=-1;i>=0 && f<0;i--)
  190.     {
  191.       if (used(i))
  192.       {
  193.         if (pal[i].red==r && pal[i].green==g && pal[i].blue==b)
  194.     f=i;
  195.       }
  196.       else
  197.         u=i;
  198.     }
  199.   } else { f=-1; u=-1; }
  200.   if (f<0)
  201.   {
  202.     if (u>=0)
  203.     { pal[u].red=r;
  204.       pal[u].green=g;
  205.       pal[u].blue=b;
  206.       set_used(u);
  207.       f=u;
  208.     }
  209.     else
  210.     {
  211.       for (i=0,f=0,u=10000;i<ncolors;i++)
  212.       { c=(pal[i].red-r)*(pal[i].red-r)+
  213.       (pal[i].green-g)*(pal[i].green-g)+
  214.       (pal[i].blue-b)*(pal[i].blue-b);
  215.     if (c<u)
  216.     { f=i;
  217.       u=c;
  218.     }
  219.       }
  220.     }
  221.   } 
  222.   return f;
  223. }
  224.  
  225. void palette::defaults()
  226. {
  227.   int i;
  228.   set(0,0,0,0);
  229.   set_used(0);
  230.   for (i=1;i<ncolors;i++)
  231.     set_unused(i);
  232.   if (ncolors==256)
  233.     for (i=0;i<ncolors;i++)
  234.       set(i,RED3(i),GREEN3(i),BLUE2(i));
  235.   else if (ncolors==16)
  236.     for (i=0;i<ncolors;i++)
  237.       set(i,255-i&3,255-(i&4)>>2,255-(i&8)>>3);
  238.   else
  239.     for (i=0;i<ncolors;i++)
  240.       set(i,255-i%3,255-(i+1)%3,255-(i+2)%3);
  241. }
  242.  
  243. void palette::shift(int amount)
  244. {
  245.   int i;
  246.   unsigned char m;
  247.   if (amount<0)
  248.   {
  249.  
  250.     m=-amount;
  251.     for (i=0;i<ncolors*3;i++)
  252.       ((unsigned char *) pal)[i]>>=m;
  253.   }
  254.   else if (amount>0)
  255.   {
  256.     m=amount;
  257.     for (i=0;i<ncolors*3;i++)
  258.       ((unsigned char *) pal)[i]<<=m;
  259.   }
  260. }
  261.  
  262.  
  263.  
  264. void palette::set(int x, unsigned char red, char unsigned green, char unsigned blue)
  265. { CONDITION(x>=0 && x<ncolors,"Pallete::set passed bad x");
  266.   CONDITION((int)red<=ncolors && (int)green<=ncolors && (int)blue<=ncolors,
  267.         "pallette::set color values bigger than palette");
  268.   pal[x].red=red; pal[x].green=green; pal[x].blue=blue;
  269. }
  270.  
  271. void palette::get(int x, unsigned char &red, unsigned char &green, unsigned char &blue)
  272. { CONDITION(x>=0 && x<ncolors,"Pallete::get passed bad x");
  273.   red=pal[x].red; green=pal[x].green; blue=pal[x].blue;
  274. }
  275. palette::~palette()
  276. { if (pal) jfree(pal);
  277.   if (usd) jfree(usd);
  278. }
  279.  
  280. palette::palette(int number_colors)
  281. {
  282.   CONDITION(number_colors>0,"palette::constructor - need at least one color!");
  283.   ncolors=number_colors;
  284.   bg=0;
  285.   
  286.   pal=(color *)jmalloc(ncolors*sizeof(color),"palette");
  287.   usd=(unsigned char *)jmalloc(ncolors/8+1,"palette used array");
  288. }
  289.  
  290.  
  291.  
  292. quant_node::~quant_node()
  293. {
  294. /*  if (!is_leaf())
  295.   { for (i=0;i<8;i++)
  296.       if (children[i])
  297.       {    delete children[i];
  298.     children[i]=NULL;
  299.       }
  300.   } */
  301. }
  302.  
  303.  
  304. /*void quant_node::prune()
  305. {
  306.   int t,r,g,b;
  307.   CONDITION(!is_leaf(),"Cannot prune a leaf!");
  308.   total(t,r,g,b);
  309.   red=r/t;
  310.   green=g/t;
  311.   blue=b/t;
  312.   be_childish();
  313. } */
  314.  
  315. void quant_node::total(int &tnodes, int &tr, int &tg, int &tb)
  316. {
  317.   int i;
  318.   if (is_leaf())
  319.   { tnodes+=tot;
  320.     tr+=red*tot;
  321.     tg+=green*tot;
  322.     tb+=blue*tot;
  323.   }
  324.   else
  325.   { for (i=0;i<8;i++)
  326.       if (children[i])
  327.     children[i]->total(tnodes,tr,tg,tb);
  328.   }
  329. }
  330.  
  331. quant_node::quant_node(int level, quant_node *dad,
  332.     unsigned char r, unsigned char g, unsigned char b)
  333. {
  334.   int i;
  335.   CONDITION(level<=8,"Tree cannot have more than eight levels");
  336.   if (level==8)
  337.     be_childish();
  338.   else
  339.     for (i=0;i<8;i++) children[i]=NULL;
  340.   padre=dad;
  341.   red=r; green=g; blue=b;
  342.   tot=0;
  343. }
  344.  
  345. quant_palette::quant_palette(int max_colors)
  346. { root=NULL; nc=0; mx=max_colors; }
  347.  
  348. void quant_palette::re_delete(quant_node *who, int lev)  // removes all children from memory
  349. { int x;                                  // and recurses down
  350.   if (who)
  351.   {
  352.     if (!who->is_leaf())
  353.     { for (x=0;x<8;x++)
  354.     if (who->children[x])
  355.     {
  356.       CONDITION(lev<8,"Levl > 7");
  357.       re_delete(who->children[x],lev+1);
  358.       level[lev].unlink((linked_node *)who->children[x]);
  359.       delete who->children[x];
  360.     }
  361.     }
  362.   }
  363. }
  364.  
  365. void quant_palette::prune()
  366. {
  367.   int pruned,lev,x,r,g,b,t;
  368.   quant_node *p,*f;
  369.   for (pruned=0,lev=8;lev>1 && !pruned;lev--)
  370.   {
  371.     p=(quant_node *)level[lev-1].first();
  372.     if (p)
  373.     { do
  374.       {
  375.     f=p->father();
  376.     for (x=0;x<8 && !pruned;x++)
  377.       if (f->children[x])
  378.         if (f->children[x]->next()!=p->next())        // if this son is not me!
  379.         pruned=1;                   //  I have a brother! stop
  380.        p=(quant_node *)p->next();
  381.       } while ((linked_node *) p!=level[lev-1].first() && !pruned);
  382.     }
  383.   }
  384.   CONDITION(lev>0,"could not prune!");
  385.   t=0; r=0; g=0; b=0;
  386.   f->total(t,r,g,b);
  387.   if (t<=1)
  388.   {
  389.     t=0; r=0; g=0; b=0;
  390.     f->total(t,r,g,b);
  391.   }
  392.   CONDITION(t>1,"Should be more colors\n");
  393.   dprintf("%d Pruned at level %d, r=%d, g=%d, b=%d, total nodes off = %d\n",nc,
  394.     lev,r/t,g/t,b/t,t);
  395.   f->set(r/t,g/t,b/t);
  396.   nc-=t;
  397.   nc++;
  398.   re_delete(f,lev);
  399.   f->be_childish();
  400. }
  401.  
  402. void quant_palette::add_color(unsigned char r, unsigned char g, unsigned char b)
  403. {
  404.   quant_node **p,*fat;
  405.   int lev,cn,stop;
  406.   p=&root;
  407.   lev=0;
  408.   stop=0;
  409.   fat=NULL;
  410.   if (nc>=mx-1)
  411.     prune();
  412.   while (!stop)
  413.   {
  414.     lev++;
  415.     if (!(*p))
  416.     { 
  417.       if (lev>2 && !fat)
  418.     dprintf("h");
  419.       (*p)=new quant_node(lev,fat);
  420.       level[lev-1].add_end((linked_node *)(*p));
  421.     }
  422.  
  423.     if (!(*p)->is_leaf())
  424.     {
  425.       cn=((r&(256>>lev))!=0)<<2;
  426.       cn+=((g&(256>>lev))!=0)<<1;
  427.       cn+=((b&(256>>lev))!=0);
  428.       fat=(*p);
  429.       p=&((*p)->children[cn]);
  430.     } else stop=1;
  431.  
  432.   }
  433.   (*p)->set(r,g,b);
  434.   if (!(*p)->tot)
  435.     nc++;
  436.   (*p)->tot++;
  437. }
  438.  
  439. palette *quant_palette::create_pal()
  440. {
  441.   palette *p;
  442.   int i,x;
  443.   quant_node *pn;
  444.   p=new palette(mx);
  445.   for (x=0,i=7;i>=0;i++)
  446.     for (pn=(quant_node *)level[i].first();
  447.      pn!=(quant_node *)level[i].first();pn=(quant_node *)pn->next())
  448.       if (pn->is_leaf())
  449.     p->set(x++,pn->red,pn->green,pn->blue);
  450.   return p;
  451. }
  452.  
  453. quant_palette::~quant_palette()
  454. {
  455.   if (root)
  456.   {
  457.     re_delete(root,1);
  458.     delete root;
  459.   }
  460. }
  461.  
  462. unsigned char palette::brightest(int all)
  463. { unsigned char r,g,b,bri;
  464.   unsigned i;
  465.   long brv;
  466.   brv=0; bri=0;
  467.  
  468.   for (i=0;i<ncolors;i++)
  469.   { if (all || used(i))
  470.     {
  471.       get(i,r,g,b);
  472.       if ((long)r*(long)g*(long)b>brv)
  473.       { brv=(long)r*(long)g*(long)b;
  474.     bri=i;
  475.       }
  476.     }
  477.   }
  478.  
  479.   return bri;
  480. }
  481.  
  482. unsigned char palette::darkest(int all, int noblack)
  483. { unsigned char r,g,b,bri;
  484.   unsigned i;
  485.   long brv,x;
  486.   brv=(long)258*(long)258*(long)258; bri=0;
  487.  
  488.   for (i=0;i<ncolors;i++)
  489.   { if (all || used(i))
  490.     {
  491.       get(i,r,g,b);
  492.       x=(long)r*(long)g*(long)b;
  493.       if (x<brv && (x || !noblack))
  494.       { brv=(long)r*(long)g*(long)b;
  495.     bri=i;
  496.       }
  497.     }
  498.   }
  499.   return bri;
  500. }
  501.  
  502.  
  503.  
  504. palette *last_loaded()
  505. { return lastl; }
  506.  
  507. void palette::fade_to(int total_fades, int fade_on, int dest_r, int dest_g, int dest_b)
  508. {
  509.   unsigned char *sl=(unsigned char *)addr();
  510.   int i;  
  511.   for (i=0;i<ncolors;i++)
  512.   {
  513.     *(sl++)=(( dest_r-(int)*sl)*fade_on/total_fades+*sl);
  514.     *(sl++)=(( dest_g-(int)*sl)*fade_on/total_fades+*sl);
  515.     *(sl++)=(( dest_b-(int)*sl)*fade_on/total_fades+*sl);    
  516.   }  
  517. }
  518.